﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using System.Web.Mvc;
using VacationsRequest.Models;
using System.Web.Security;
using System.Collections;
using System.Text;
using System.IO;
using System.Net.Mail;
using System.Web.Mvc.Html;
using System.Net;

namespace VacationsRequest.Controllers
{
    public class ApprovalStatusController : Controller
    {
        private VacationApprovalDBContext db = new VacationApprovalDBContext();
        private VacationDayDBContext dbVacations = new VacationDayDBContext();
        private EmployeeDBContext dbEmployees = new EmployeeDBContext();

        //
        // GET: /ApprovalStatus/

        public ActionResult Index(bool? _pending, bool? _accepted, bool? _rejected)
        {
            if (_pending == null)
            {
                _pending = true;
            }
            if (_accepted == null)
            {
                _accepted = false;
            }
            if (_rejected == null)
            {
                _rejected = false;
            }

            Guid userId = (Guid)Membership.GetUser().ProviderUserKey;

            var vacationapproval = db.VacationApproval.Include(v => v.Status);
            vacationapproval = vacationapproval.Where(u => u.Deleted == false);
            vacationapproval = vacationapproval.Where(u => u.IdUserApprove == userId);

            List<int> ids = new List<int>();

            if (_pending.Value)
            {
                ids.Add(1);
            }
            if (_accepted.Value)
            {
                ids.Add(2);
            }
            if (_rejected.Value)
            {
                ids.Add(3);
            }

            vacationapproval = vacationapproval.Where(x => ids.Contains(x.IdStatus));

            var allEmployees = dbEmployees.Employees.ToArray();
            var allApprovals = vacationapproval.ToList();

            var vacApproval = from u in allApprovals
                              join t in allEmployees on u.IdEmployee equals t.ID
                              select new ApprovalList
                              {
                                  ID = u.ID,
                                  DateCreated = u.DateCreated,
                                  FromDate = u.FromDate,
                                  ToDate = u.ToDate,
                                  EmployeeName = t.FirstName + " " + t.FirstLastName + " " + t.SecondLastName,
                                  IdStatus = u.IdStatus,
                                  Status = u.Status.Description,
                                  NumDays = u.NumDays,
                                  ApproverComment = u.ApproverComment,
                                  Notified = u.Notified
                              };

            return View(vacApproval.ToList());
        }

        //
        // GET: /ApprovalStatus/Details/5

        public ViewResult Details(Guid id)
        {
            VacationApproval vacationapproval = db.VacationApproval.Find(id);

            var vacationdays = (from u in dbVacations.VacationDays
                                where u.IdApproval == id
                                select u);

            ViewBag.ApproverName = Membership.GetUser(vacationapproval.IdUserApprove).UserName;

            Employee employee = dbEmployees.Employees.Find(vacationapproval.IdEmployee);
            ViewBag.EmployeeName = employee.FirstName + " " + employee.FirstLastName + " " + employee.SecondLastName;
            vacationdays = vacationdays.OrderByDescending(s => s.Date);
            ViewBag.VacationsList = vacationdays.ToList();

            return View(vacationapproval);
        }

        //
        // GET: /ApprovalStatus/Create

        public ActionResult Create()
        {
            ViewBag.IdStatus = new SelectList(db.ApprovalStatus, "ID", "Description");
            return View();
        }

        //
        // POST: /ApprovalStatus/Create

        [HttpPost]
        public ActionResult Create(VacationApproval vacationapproval)
        {
            if (ModelState.IsValid)
            {
                vacationapproval.ID = Guid.NewGuid();
                db.VacationApproval.Add(vacationapproval);
                db.SaveChanges();
                return RedirectToAction("Index");
            }

            ViewBag.IdStatus = new SelectList(db.ApprovalStatus, "ID", "Description", vacationapproval.IdStatus);
            return View(vacationapproval);
        }

        //
        // GET: /ApprovalStatus/Edit/5

        public ActionResult Edit(Guid id)
        {
            VacationApproval vacationapproval = db.VacationApproval.Find(id);
            ViewBag.IdStatus = new SelectList(db.ApprovalStatus, "ID", "Description", vacationapproval.IdStatus);
            Employee employee = dbEmployees.Employees.Find(vacationapproval.IdEmployee);
            ViewBag.EmployeeName = employee.FirstName + " " + employee.FirstLastName + " " + employee.SecondLastName;
            return View(vacationapproval);
        }

        //
        // POST: /ApprovalStatus/Edit/5

        [HttpPost]
        public ActionResult Edit(VacationApproval vacationapproval)
        {
            if (ModelState.IsValid)
            {
                vacationapproval.ApprovalDate = DateTime.Now;
                db.Entry(vacationapproval).State = EntityState.Modified;
                db.SaveChanges();

                SendEmail(dbEmployees.Employees.Find(vacationapproval.IdEmployee), vacationapproval.FromDate, vacationapproval.ToDate, vacationapproval.ID, vacationapproval.ApproverComment, vacationapproval.IdStatus);

                return RedirectToAction("Index");
            }
            ViewBag.IdStatus = new SelectList(db.ApprovalStatus, "ID", "Description", vacationapproval.IdStatus);
            Employee employee = dbEmployees.Employees.Find(vacationapproval.IdEmployee);
            ViewBag.EmployeeName = employee.FirstName + " " + employee.FirstLastName + " " + employee.SecondLastName;
            return View(vacationapproval);
        }

        private void SendEmail(Employee emp, DateTime pstart, DateTime pend, Guid apprId, string comment, int approvalId)
        {
            WebClient wc = new WebClient();
            byte[] x = wc.DownloadData(Request.Url.Scheme + System.Uri.SchemeDelimiter + Request.Url.Host + (Request.Url.IsDefaultPort ? "" : ":" + Request.Url.Port) + "/Reports/PrintVacationsForm/" + emp.ID.ToString() + "?requestId=" + apprId.ToString());
            MemoryStream _ms = new MemoryStream(x);
            System.Net.Mail.SmtpClient smtp = new System.Net.Mail.SmtpClient();
            MailMessage msg = new MailMessage();

            string apprEmail = Membership.GetUser(emp.IdUserApprover).Email;

            switch (approvalId)
            {
                case 2:
                    msg.Attachments.Add(new Attachment(_ms, "VacationForm_" + DateTime.Now.ToString("MM_dd_yyyy") + "_" + emp.Email + ".pdf", "application/pdf"));

                    msg.To.Add(emp.Email);
                    msg.Body = "Your vacations from " + pstart.ToShortDateString() + " to " + pend.ToShortDateString() + " have been approved. Please print and sign the attached form and deliver it to human resources department.";
                    msg.Body += "<br /><br />Additional Comments:<br /><br />" + comment;
                    msg.Subject = "Vacation Request - Vacations Approved";
                    msg.Priority = MailPriority.High;
                    msg.IsBodyHtml = true;
                    smtp.Send(msg);

                    msg = new MailMessage();

                    msg.To.Add(apprEmail);
                    msg.Body = "The vacations for " + (emp.FirstName + " " + emp.FirstLastName + " " + emp.SecondLastName).Trim() + " have been approved.";
                    msg.Body += "<br /><br />Additional Comments:<br /><br />" + comment;
                    msg.Subject = "Vacation Request - Vacations Approved for " + (emp.FirstName + " " + emp.FirstLastName + " " + emp.SecondLastName).Trim();
                    msg.Priority = MailPriority.High;
                    msg.IsBodyHtml = true;
                    smtp.Send(msg);
                    break;

                case 3:

                    msg.To.Add(emp.Email);
                    msg.Body = "Your vacations from " + pstart.ToShortDateString() + " to " + pend.ToShortDateString() + " have been rejected.";
                    msg.Body += "<br /><br />Additional Comments:<br /><br />" + comment;
                    msg.Subject = "Vacation Request - Vacations Rejected";
                    msg.Priority = MailPriority.High;
                    msg.IsBodyHtml = true;
                    smtp.Send(msg);


                    msg = new MailMessage();

                    msg.To.Add(apprEmail);
                    msg.Body = "The vacations for " + (emp.FirstName + " " + emp.FirstLastName + " " + emp.SecondLastName).Trim() + " from " + pstart.ToShortDateString() + " to " + pend.ToShortDateString() + " have been rejected.";
                    msg.Body += "<br /><br />Additional Comments:<br /><br />" + comment;
                    msg.Subject = "Vacation Request - Vacations Rejected for " + (emp.FirstName + " " + emp.FirstLastName + " " + emp.SecondLastName).Trim();
                    msg.Priority = MailPriority.High;
                    msg.IsBodyHtml = true;
                    smtp.Send(msg);

                    DeleteRejectedVacations(apprId);

                    break;


            }
        }

        private void DeleteRejectedVacations(Guid id)
        {
            VacationApproval vacationapproval = db.VacationApproval.Find(id);
            vacationapproval.Deleted = true;

            db.Entry(vacationapproval).State = EntityState.Modified;
            db.SaveChanges();

            var vacationdays = (from u in dbVacations.VacationDays
                                where u.IdApproval == id
                                select u);

            foreach (VacationDay vd in vacationdays)
            {
                dbVacations.VacationDays.Remove(vd);
            }

            dbVacations.SaveChanges();
        }

        //
        // GET: /ApprovalStatus/Delete/5

        public ActionResult Delete(Guid id)
        {
            VacationApproval vacationapproval = db.VacationApproval.Find(id);
            ViewBag.ApproverName = Membership.GetUser(vacationapproval.IdUserApprove).UserName;
            return View(vacationapproval);
        }

        //
        // POST: /ApprovalStatus/Delete/5

        [HttpPost, ActionName("Delete")]
        public ActionResult DeleteConfirmed(Guid id)
        {
            VacationApproval vacationapproval = db.VacationApproval.Find(id);
            vacationapproval.Deleted = true;
            int idEmployee = vacationapproval.IdEmployee;

            db.Entry(vacationapproval).State = EntityState.Modified;
            db.SaveChanges();

            var vacationdays = (from u in dbVacations.VacationDays
                                where u.IdApproval == id
                                select u);

            foreach (VacationDay vd in vacationdays)
            {
                dbVacations.VacationDays.Remove(vd);
            }

            dbVacations.SaveChanges();

            if (User.IsInRole("Administrator"))
            {
                return RedirectToAction("Index", "Employees");
            }
            else
            {
                return RedirectToAction("EmployeeDetails", "VacationDays", new { id = idEmployee });
            }
        }

        protected override void Dispose(bool disposing)
        {
            db.Dispose();
            base.Dispose(disposing);
        }
    }
}